#ifndef _MEETINGHANDLER_H_
#define _MEETINGHANDLER_H_

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <assert.h>

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include "spthread.hpp"
#include "spporting.hpp"
#include "spwin32iocp.hpp"
#include "spiocpserver.hpp"

#include "spmsgdecoder.hpp"
#include "spbuffer.hpp"

#include "sphandler.hpp"
#include "spresponse.hpp"
#include "sprequest.hpp"
#include "sputils.hpp"

#include "messageutil.h"
#include "msgdecoder.h"

#include "package.h"

class UserList {
public:
	UserList();
	~UserList();

	void copy( SP_SidList * outList, SP_Sid_t * ignoreSid = NULL );
	void remove( SP_Sid_t sid );
	void add( SP_Sid_t sid );
	int getCount();

private:
	SP_SidList mList;
	sp_thread_mutex_t mMutex;
};
struct UserInfo
{
	SP_Sid_t sid;
	int meetingId;
	int session;
	std::string name;
	int password;
	int rights;
	int terminalType;
};
class MeetingInfo
{
public:
	MeetingInfo();
	~MeetingInfo();
private:
	std::map<int,UserInfo*> mUserInfoList;
	bool desktopShared;
	SP_Sid_t mDesktopSharer;
	UserList mWhiteboardShareUsers;
	sp_thread_mutex_t mMutex;
public:
	bool setSharer(SP_Sid_t sharer,Meeting::ShareType shareType);
	void add(SP_Sid_t attender,Meeting::LoginRequest* request);
	void remove(SP_Sid_t attender);
	void getUserList(SP_SidList * outList, SP_Sid_t * ignoreSid = NULL);
	int getUserCount(){ return mUserInfoList.size(); }
};
class MeetingManager
{
public:
	MeetingManager();
	~MeetingManager();

	UserList * getUserList(){ return &mOnlineSidList; }
	MeetingInfo* getMeetingInfo(int meetingId);
	bool attendMeeting(SP_Sid_t sid,Meeting::LoginRequest* request);
	bool leaveMeeting(SP_Sid_t sid,int meetingId);
private:
	UserList  mOnlineSidList;
	std::map<int,MeetingInfo*> mMapMeeting;
	sp_thread_mutex_t mMutex;
};
class MeetingHandler : public SP_Handler {
public:
	MeetingHandler( MeetingManager * meetingManager );
	virtual ~MeetingHandler();

	virtual int start( SP_Request * request, SP_Response * response );

	// return -1 : terminate session, 0 : continue
	virtual int handle( SP_Request * request, SP_Response * response );

	virtual void error( SP_Response * response );

	virtual void timeout( SP_Response * response );

	virtual void close();

private:
	SP_Sid_t mSid;
	int mMeetingId;
	MeetingManager * mMeetingManager;

	static int mMsgSeq;

	void process(Package* package, SP_Response * response);

	void broadcast( SP_Response * response, const char * buffer,size_t size, SP_Sid_t * ignoreSid = 0 );
	void broadcast( SP_Response * response, const string& msg, SP_Sid_t * ignoreSid = 0 );
};

class MeetingCompletionHandler : public SP_CompletionHandler {
public:
	MeetingCompletionHandler(){}
	~MeetingCompletionHandler(){}
	virtual void completionMessage( SP_Message * msg );
};

class MeetingHandlerFactory : public SP_HandlerFactory {
public:
	MeetingHandlerFactory( MeetingManager * meetingManager ){mMeetingManager=meetingManager;}
	virtual ~MeetingHandlerFactory(){}

	virtual SP_Handler * create() const{return new MeetingHandler(mMeetingManager);}

	virtual SP_CompletionHandler * createCompletionHandler() const{return new MeetingCompletionHandler();}

private:
	MeetingManager * mMeetingManager;
};

#endif